
/*
 * 	Mancala GUI class
 * 	Provides a visualization of the game state, and graphical means for altering the state
 *  Uses the Ucigame game engine as a framework
 */
import javax.swing.JOptionPane;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.Random;

import ucigame.*;

public class Mancala extends Ucigame
{
	private int startingStones = 4, stones;
	private boolean drawText, thinking;
	private Sprite pBucket0Img, pBucket1Img, pBucket2Img, pBucket3Img, pBucket4Img, pBucket5Img, pGoalImg, 
		oBucket0Img, oBucket1Img, oBucket2Img, oBucket3Img, oBucket4Img, oBucket5Img, oGoalImg, current;
	private Ellipse2D.Double pBucket0, pBucket1, pBucket2, pBucket3, pBucket4, pBucket5, pGoal, 
	oBucket0, oBucket1, oBucket2, oBucket3, oBucket4, oBucket5, oGoal;
	private ArrayList<Sprite> sprites;
	private Team8_Player opponent;
	private KalahPieGameState gameState;
	
	
	
	public void setup()
	{
		// set up game screen
		window.size(800, 600);
		window.title("Mancala");
		framerate(20);
		Image bck = getImage("boardBackgroud.png");
		canvas.background(bck);
		
		// Player buckets and score bucket
		pBucket0Img = makeSprite(getImage("bucket.png"));
		pBucket1Img = makeSprite(getImage("bucket.png"));
		pBucket2Img = makeSprite(getImage("bucket.png"));
		pBucket3Img = makeSprite(getImage("bucket.png"));
		pBucket4Img = makeSprite(getImage("bucket.png"));
		pBucket5Img = makeSprite(getImage("bucket.png"));
		pGoalImg = makeSprite(getImage("score.png"));
		
		// Opponent buckets and score bucket
		oBucket0Img = makeSprite(getImage("bucket.png"));
		oBucket1Img = makeSprite(getImage("bucket.png"));
		oBucket2Img = makeSprite(getImage("bucket.png"));
		oBucket3Img = makeSprite(getImage("bucket.png"));
		oBucket4Img = makeSprite(getImage("bucket.png"));
		oBucket5Img = makeSprite(getImage("bucket.png"));
		oGoalImg = makeSprite(getImage("score.png"));
	
		// positions (tentative)
		oGoalImg.position(20, 120);
		oBucket0Img.position(125, 150);
		oBucket1Img.position(215, 150);
		oBucket2Img.position(305, 150);
		oBucket3Img.position(395, 150);
		oBucket4Img.position(485, 150);
		oBucket5Img.position(575, 150);
		
		pBucket0Img.position(125, 300);
		pBucket1Img.position(215, 300);
		pBucket2Img.position(305, 300);
		pBucket3Img.position(395, 300);
		pBucket4Img.position(485, 300);
		pBucket5Img.position(575, 300);
		pGoalImg.position(665, 120);
		
		// Ellipse2d objects for boundary detection on sprites
		int bucketX = oBucket0Img.width(), bucketY = oBucket0Img.height();
		oBucket0 = new Ellipse2D.Double(oBucket0Img.x(), oBucket0Img.y(), bucketX, bucketY);
		oBucket1 = new Ellipse2D.Double(oBucket1Img.x(), oBucket1Img.y(), bucketX, bucketY);
		oBucket2 = new Ellipse2D.Double(oBucket2Img.x(), oBucket2Img.y(), bucketX, bucketY);
		oBucket3 = new Ellipse2D.Double(oBucket3Img.x(), oBucket3Img.y(), bucketX, bucketY);
		oBucket4 = new Ellipse2D.Double(oBucket4Img.x(), oBucket4Img.y(), bucketX, bucketY);
		oBucket5 = new Ellipse2D.Double(oBucket5Img.x(), oBucket5Img.y(), bucketX, bucketY);
		
		pBucket0 = new Ellipse2D.Double(pBucket0Img.x(), pBucket0Img.y(), bucketX, bucketY);
		pBucket1 = new Ellipse2D.Double(pBucket1Img.x(), pBucket1Img.y(), bucketX, bucketY);
		pBucket2 = new Ellipse2D.Double(pBucket2Img.x(), pBucket2Img.y(), bucketX, bucketY);
		pBucket3 = new Ellipse2D.Double(pBucket3Img.x(), pBucket3Img.y(), bucketX, bucketY);
		pBucket4 = new Ellipse2D.Double(pBucket4Img.x(), pBucket4Img.y(), bucketX, bucketY);
		pBucket5 = new Ellipse2D.Double(pBucket5Img.x(), pBucket5Img.y(), bucketX, bucketY);
		
		// add to sprites ArrayList
		sprites = new ArrayList<Sprite>();
		sprites.add(pBucket0Img);
		sprites.add(pBucket1Img);
		sprites.add(pBucket2Img);
		sprites.add(pBucket3Img);
		sprites.add(pBucket4Img);
		sprites.add(pBucket5Img);
		sprites.add(pGoalImg);
		sprites.add(oBucket0Img);
		sprites.add(oBucket1Img);
		sprites.add(oBucket2Img);
		sprites.add(oBucket3Img);
		sprites.add(oBucket4Img);
		sprites.add(oBucket5Img);
		sprites.add(oGoalImg);
		
		// set up KalahPie game
		gameState = new KalahPieGameState(startingStones);
		opponent = new Team8_Player(1);
		thinking = false;
	}
	
	public void draw()
	{
		canvas.clear();
		Random r = new Random();

		for (Sprite s : sprites)
		{
			int x = 10;
			int y = 10;
			s.draw();
			int[] indexes = getIndexes(s);
			if (indexes[0]!=-1 && indexes[1]!=-1){
				canvas.putText("Stones: " + gameState.stonesAt(indexes[0],indexes[1]), s.x()+10,s.y()-5 );
			
				for(int i=0;i<gameState.stonesAt(indexes[0], indexes[1]);i++){
					Sprite stoneImg = makeSprite(getImage("stone.png"));
					//stoneImg.position(s.x()+r.nextInt(50),s.y()+r.nextInt(50));
					stoneImg.position(s.x()+x,s.y()+y);
					y+=10;
					if(y>30){
						x+=10;
						y=10;
					}
					stoneImg.draw();
				}
			}
				

		}
		int x = 20;
		int y = 80;
		pGoalImg.draw();
		if(gameState.CurrentPlayer==1){
			canvas.putText("Computer's turn", 350, 100);
		}
		else{
			canvas.putText("Your turn", 350, 450);
		}
		
		canvas.putText("Scored: " + gameState.getScore(0), pGoalImg.x()+22, pGoalImg.y()+pGoalImg.height()+15);
		for(int j=0;j<gameState.getScore(0);j++){
			Sprite stoneImg = makeSprite(getImage("stone.png"));
			//stoneImg.position(pGoalImg.x()+r.nextInt(50),pGoalImg.y()+r.nextInt(200));
			stoneImg.position(pGoalImg.x()+x,pGoalImg.y()+y);
			y+=20;
			if(y>240){
				y = 80;
				x+=10;
			}
			stoneImg.draw();
		}
		oGoalImg.draw();
		x = 20;
		y = 80;
		canvas.putText("Scored: " + gameState.getScore(1), oGoalImg.x()+22, oGoalImg.y()-19);
		for(int z=0;z<gameState.getScore(1);z++){
			Sprite stoneImg = makeSprite(getImage("stone.png"));
			//stoneImg.position(oGoalImg.x()+r.nextInt(50),oGoalImg.y()+r.nextInt(200));
			stoneImg.position(oGoalImg.x()+x,oGoalImg.y()+y);
			y+=20;
			if(y>240){
				y = 80;
				x+= 10;
			}
			stoneImg.draw();
		}

		
		//if (drawText && (current != null))
		//{
		//	canvas.putText(stones, current.x()+20, current.y()-10);	
		//}
	}
	
	private void performEndGame() 
	{	
        System.out.println("Performing player 1 post game actions...");
        opponent.postGameActions(gameState);

        gameState.computeFinalScore();
        int playerScore, oppScore;
        playerScore = gameState.getScore(0);
        oppScore = gameState.getScore(1);
        
        String message;
        if (playerScore > oppScore)
        	message = "You beat your opponent "+playerScore+" to "+oppScore;
        else if (oppScore > playerScore)
        	message = "Your opponent beat you "+playerScore+" to "+oppScore;
        else
        	message = "You and your opponent tied with "+playerScore+" stones.";
        
        int replay = JOptionPane.showConfirmDialog(null, message +"\n\nWould you like to replay the game?", 
        		"Game Complete", JOptionPane.YES_NO_OPTION);
        if (replay == JOptionPane.YES_OPTION)
        	setup();
        else
        	System.exit(0);
	}
	
	// returns a bucket sprite if mouse is hovering over one, otherwise returns null
	private Sprite isMouseOver(double x, double y) 
	{
		if (pBucket0.contains(x, y)) 
			return pBucket0Img;
		if (pBucket1.contains(x, y))
			return pBucket1Img;
		if (pBucket2.contains(x, y))
			return pBucket2Img;
		if (pBucket3.contains(x, y))
			return pBucket3Img;
		if (pBucket4.contains(x, y))
			return pBucket4Img;
		if (pBucket5.contains(x, y))
			return pBucket5Img;
		
		if (oBucket0.contains(x, y))
			return oBucket0Img;
		if (oBucket1.contains(x, y))
			return oBucket1Img;
		if (oBucket2.contains(x, y))
			return oBucket2Img;
		if (oBucket3.contains(x, y))
			return oBucket3Img;
		if (oBucket4.contains(x, y))
			return oBucket4Img;
		if (oBucket5.contains(x, y))
			return oBucket5Img;
		else
			return null;
	}
	
	// returns array with indexes of bucket sprites ([x,y])
	// if opponent's goal, returns [0][-1], if player's goal returns [-1][0], else returns [-1][-1]
	private int[] getIndexes(Sprite sprite)
	{	
		// PLAYER BUCKETS
		if (sprite == pBucket0Img) 
			return new int[] {0,0};
		if (sprite == pBucket1Img)
			return new int[] {0,1}; 
		if (sprite == pBucket2Img)
			return new int[] {0,2};
		if (sprite == pBucket3Img)
			return new int[] {0,3};
		if (sprite == pBucket4Img)
			return new int[] {0,4};
		if (sprite == pBucket5Img)
			return new int[] {0,5};			
		
		// OPPONENT BUCKETS
		if (sprite == oBucket0Img) 
			return new int[] {1,0};
		if (sprite == oBucket1Img)
			return new int[] {1,1};
		if (sprite == oBucket2Img)
			return new int[] {1,2};
		if (sprite == oBucket3Img)
			return new int[] {1,3};
		if (sprite == oBucket4Img)
			return new int[] {1,4};
		if (sprite == oBucket5Img)
			return new int[] {1,5};
		
		// GOALS
		if (sprite == pGoalImg)
			return new int[] {-1,0};
		if (sprite == oGoalImg)
			return new int[] {0,-1};
		
		return new int[] {-1,-1};
	}
	
	public void opponentMoveTimer()
	{	
		if (gameState.CurrentPlayer()==1 && !thinking)
		{	try {
				thinking = true;
				int move = opponent.getMove(gameState);
				gameState.play(move);
				thinking = false;
			} catch (Exception e){};
			
			if (gameState.CurrentPlayer!=1)
				stopTimer("opponentMove");
			
			if (gameState.checkEndGame())
			{	stopTimer("opponentMove");	
				startTimer("endGame",1500);
			}
		} else
			{
				System.out.println("Not opponent's turn yet");
			}
	}
	
	public void endGameTimer()
	{	stopTimer("endGame");
		performEndGame();
	}
	
	public void hoverTextDelayTimer()
	{	stopTimer("hoverTextDelay");
		drawText = true;
	}
	
	public void onMouseMoved()
	{
		Sprite last = current;
		current = isMouseOver(mouse.x(),mouse.y());
		
		if (current != null)	
		{
			int[] indexes = getIndexes(current);
			int indexX = indexes[0], indexY = indexes[1];
			stones = gameState.stonesAt(indexX, indexY);
			if (last != current)
				startTimer("hoverTextDelay",1000);
		} 
		else
			drawText = false;
	}
	
	public void onMousePressed()
	{
		Sprite select = isMouseOver(mouse.x(),mouse.y());
		if (select != null)
		{	int[] indexes = getIndexes(select);
			if ((indexes[0]!=-1) && (indexes[1]!=-1))
			{	if (gameState.CurrentPlayer==0 && indexes[0]==0)
				{	
					if (gameState.validMove(indexes[1]))
					{	// if a valid move was selected during human player's turn
						try {
							gameState.play(indexes[1]);
							if (gameState.checkEndGame())
								performEndGame();
						} catch (Exception e) {
							JOptionPane.showMessageDialog(null, "An exception occured");
						}
						
						if (gameState.CurrentPlayer!=0)
							startTimer("opponentMove",1500);
					} else
						System.out.println("Invalid move");
						//JOptionPane.showMessageDialog(null, "The selected move is not valid");
				}
			}			
		} else
			System.out.println("Sprite was null");
	}

	public void onKeyPress()
    {	
		
    }
}

